
// My header
#include "DragDrop.h"

// Fridge
#include "../Controller/Controller_Main.h"
#include "../Input.h"
#include "../InputKeys.h"
#include "../TextureManager.h"
#include "Widget.h"

//external
#include <math.h>

const float fDRAG_DROP_ENGAGE_DISTANCE = 5.0f;

DRAG_STATE		DragDropManager::s_eDragState		= DRAG_STATE_NONE;
u_int			DragDropManager::s_uDragOriginX		= 0;
u_int			DragDropManager::s_uDragOriginY		= 0;
Widget*			DragDropManager::s_pxWidgetOrigin	= 0;
DragDropData	DragDropManager::s_xDragDropData;

void DragDropManager::Initialise()
{
}

void DragDropManager::Update( )
{
	Widget* pxTopLevelWidget = reinterpret_cast<Widget*>( Controller_Main::GetWindowPanel() );
	const Input* pxInput = Controller_Main::GetInputHandler();

	switch( s_eDragState )
	{
		case DRAG_STATE_NONE:
		{
			// Check if the user depressed the key on a widget
			if( pxInput->MouseButtonPressed( INPUT_MOUSE_BUTTON_LEFT ) )
			{
				s_pxWidgetOrigin = pxTopLevelWidget->FindChildWidgetAt( pxInput->MousePositionX(), pxInput->MousePositionY() );
				s_uDragOriginX = pxInput->MousePositionX();
				s_uDragOriginY = pxInput->MousePositionY();
				s_eDragState = DRAG_STATE_MOUSEDOWN;
			}
		}
		break;

		case DRAG_STATE_MOUSEDOWN:
		{
			bool bFailToDrag = false;

			if( pxInput->MouseButtonReleased( INPUT_MOUSE_BUTTON_LEFT ) )
			{
				bFailToDrag = true;
			}
			else
			{
				// Have we moved the mouse enough with the button down to start a drag operation?
				const float fDist = sqrtf( powf( static_cast<float>( s_uDragOriginX ) - static_cast<float>( pxInput->MousePositionX() ), 2.0f ) + powf( static_cast<float>( s_uDragOriginY ) - static_cast<float>( pxInput->MousePositionY() ), 2.0f ) );
				if( fDist > fDRAG_DROP_ENGAGE_DISTANCE )
				{
					if( s_pxWidgetOrigin )
					{
						BeginDragDropCallback pfnBeginDragFunc = s_pxWidgetOrigin->GetBeginDragDropCallback();

						s_xDragDropData.Clear();

						// See if this widget can begin dragging
						if( pfnBeginDragFunc && pfnBeginDragFunc( &s_xDragDropData, s_pxWidgetOrigin ) )
						{
							s_eDragState = DRAG_STATE_DRAGGING;
						}
						else
						{
							bFailToDrag = true;
						}
					}
				}
			}

			if( bFailToDrag )
			{
				s_eDragState = DRAG_STATE_NONE;
				s_pxWidgetOrigin = 0;
				s_uDragOriginX = 0;
				s_uDragOriginY = 0;
			}
		}
		break;

		case DRAG_STATE_DRAGGING:
		{
			if( pxInput->MouseButtonReleased( INPUT_MOUSE_BUTTON_LEFT ) )
			{
				Widget* pxOver = pxTopLevelWidget->FindChildWidgetAt( pxInput->MousePositionX(), pxInput->MousePositionY() );
				if( pxOver )
				{
					DragOverCallback pfnDragOverFunc = pxOver->GetDragOverCallback();
					if( pfnDragOverFunc && pfnDragOverFunc( &s_xDragDropData, pxOver ) )
					{
						// Drop here
						EndDragDropCallback pfnEndDragFunc = pxOver->GetEndDragDropCallback();
						if( pfnEndDragFunc )
						{
							pfnEndDragFunc( &s_xDragDropData, pxOver );
						}
					}
				}
				s_xDragDropData.Clear();
				s_eDragState = DRAG_STATE_NONE;
			}
		}
		break;
	}
}

void DragDropManager::Render()
{
	Widget* pxTopLevelWidget = reinterpret_cast<Widget*>( Controller_Main::GetWindowPanel() );
	const Input* pxInput = Controller_Main::GetInputHandler();

	StringHash xIconHash = INVALID_STRING_HASH;

	switch( s_eDragState )
	{
		case DRAG_STATE_DRAGGING:
		{
			Widget* pxOver = pxTopLevelWidget->FindChildWidgetAt( pxInput->MousePositionX(), pxInput->MousePositionY() );
			if( pxOver )
			{
				DragOverCallback pfnDragOverFunc = pxOver->GetDragOverCallback();
				if( pfnDragOverFunc && pfnDragOverFunc( &s_xDragDropData, pxOver ) )
				{
					// The widget we are over could potentially accept this, so render an appropriate icon
					xIconHash = s_xDragDropData.m_xIcon;
				}
			}

			if( xIconHash == INVALID_STRING_HASH )
			{
				// Cannot drop here, or no widget
				xIconHash = GetStringHash( "NoDrop32" );
			}
		}
		break;
	}

	if( xIconHash != INVALID_STRING_HASH )
	{
		TextureManager* pxTextureManager = Controller_Main::GetTextureManager();

		if( pxTextureManager )
		{
			int iTextureID = pxTextureManager->GetTextureID( xIconHash );
			
			glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
			glBindTexture( GL_TEXTURE_2D, iTextureID );

			glBegin( GL_QUADS );

			u_int uX = pxInput->MousePositionX();
			u_int uY = pxInput->MousePositionY();

			// icons rendered as 32 x 32 

			glTexCoord2f( 0.0f, 0.0f );
			glVertex2i( uX - 16, uY - 16 );
			glTexCoord2f( 0.0f, 1.0f );
			glVertex2i( uX - 16, uY + 16 );
			glTexCoord2f( 1.0f, 1.0f );
			glVertex2i( uX + 16, uY + 16 );
			glTexCoord2f( 1.0f, 0.0f );
			glVertex2i( uX + 16, uY - 16 );

			glEnd();
		}
	}
}

void DragDropManager::Shutdown()
{
}

bool DragDropManager::IsDragging()
{
	return ( s_eDragState != DRAG_STATE_NONE );
}

//eof
